import React, { FC, FunctionComponentElement } from "react";

interface Ant {
  name: string;
  weight: number;
}
interface Fly {
  fly: boolean;
}
// 交叉类型
type FlyAnt = Ant & Fly;
// 联合类型
type FlyOrAnt = Ant | Fly;

const feng: FlyOrAnt = {
  name: "123",
  weight: 123,
};
// 可选类型
type Abc = Partial<FlyAnt>;
type omit = Omit<FlyAnt, "weight">;
type ReadOnlyType<T> = {
  readonly [p in keyof T]: T[p];
};

type A = ReadOnlyType<FlyAnt>;

const TypeScript: FC = ({ children }) => {
  const renderChildren = () =>
    React.Children.map(children, (item, index) => {
      const element = item as FunctionComponentElement<{ currentKey: string }>;
      return React.cloneElement(element, {
        currentKey: index.toString(),
      });
    });

  const one: FlyAnt = {
    name: "123",
    weight: 10,
    fly: true,
  };
  const two: FlyOrAnt = {
    fly: true,
  };

  // 类型判断
  const foo = (num: number | string) => {
    if (typeof num === "string") {
    } else {
    }
  };
  // 复杂类型的（key）
  type keys = keyof Fly;

  // 去除必填
  type Require<T> = {
    [p in keyof T]-?: T[p];
  };
  interface PersonItem {
    name?: string;
    age?: number;
    phone: number;
  }
  type Person = Require<PersonItem>;

  // 提取 这里的 extends 不是类、接口的继承，而是对于类型的判断和约束，意思是判断 T 能否赋值给 K
  type Pick<T, K extends keyof T> = {
    // 遍历 K
    [P in K]: T[P];
  };

  type Phone = Pick<PersonItem, "phone" | "age">;

  type Exclude<T, U> = T extends U ? never : T;

  type person1 = Exclude<Ant, "name">;
  // 排除
  type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

  // 可以用 infer P 来标记一个泛型，表示这个泛型是一个待推断的类型，并且可以直接使用(只能在extends中使用不知道什么类型的时候使用)
  type ParamType<T> = T extends (param: infer P) => any ? P : T;
  const a: ParamType<(a: number) => {}> = 1231;

  /** 
   * export function useFetchHandle<T>(
  api: (params?: any) => Promise<T>,
  handleSuccess: (data: T) => void,
  handleError?: (error: T) => void
) {
  */
  // 结果推论
  type ResultOf<T extends (params: any) => Promise<any>> = ReturnType<T>;

  // 提取函数的返回值(提取函数的返回值)（T的值不确定）
  type GetResult<T extends (params: any) => any> =
    ReturnType<T> extends Promise<infer U> ? U : ReturnType<T>;

  type result = GetResult<() => Promise<number>>;
  type result2 = GetResult<() => number>;

  type SomePerson = "zs" | "lisi" | "wangwu";
  type Group = Record<SomePerson, Ant>;

  type Result<T extends (param: any) => any> = ReturnType<T> extends Promise<
    infer U
  >
    ? U
    : T;

  return <div>类型的定义</div>;
};

export default TypeScript;
